WebDAV : Web-based Distributed Authoring and Versioning
WebDAV
(Web based Distributed Authoring and Versioning) is a communication protocol based on HTTP 1.1 protocol. It extends HTTP 1.1, and adds some new methods in addition to several HTTP standard methods such as GET
, POST
, HEAD
, so that applications can directly read and write to the server, and supports locking and unlocking of write files.
This module is a webapp
middleware. It implements the WebDAV
server and supports the following features:
- User management;
- User access authentication;
- Authority management;
- Support physical file system and virtual file system;
- One webdav server can dynamically mount multiple file systems.
User can use the following code to import the webdav
module.
var webdav = require('middleware').webdav;
User can user the middleware as follow:
// Create webdav server
const server = new webdav.WebDAVServer(/* options */);
// Mount the WebDAVServer instance
app.use(webdav.route('/', server));
Support
The following shows webdav
module APIs available for each permissions.
User Mode | Privilege Mode | |
---|---|---|
webdav.WebDAVServer | ● | ● |
webdav.route | ● | ● |
server.rootFileSystem | ● | ● |
server.setFileSystem | ● | ● |
server.removeFileSystem | ● | ● |
server.getFileSystemPath | ● | ● |
server.getFileSystem | ● | ● |
server.getChildFileSystems | ● | ● |
server.on | ● | ● |
server.removeEvent | ● | ● |
server.beforeRequest | ● | ● |
server.afterRequest | ● | ● |
server.createExternalContext | ● | ● |
webdav.SimpleUser | ● | ● |
user.username | ● | ● |
user.password | ● | ● |
user.isAdministrator | ● | ● |
user.isDefaultUser | ● | ● |
user.uid | ● | ● |
webdav.SimpleUserManager | ● | ● |
userManager.addUser | ● | ● |
userManager.delUser | ● | ● |
userManager.getUsers | ● | ● |
userManager.getDefaultUser | ● | ● |
userManager.getUserByName | ● | ● |
userManager.getUserByNamePassword | ● | ● |
webdav.SimplePathPrivilegeManager | ● | ● |
privilege.setRights | ● | ● |
privilege.getRights | ● | ● |
webdav.HTTPBasicAuthentication | ● | ● |
webdav.HTTPDigestAuthentication | ● | ● |
webdav.PhysicalFileSystem | ● | ● |
webdav.VirtualFileSystem | ● | ● |
webdav.RequestContext | ● | ● |
context.requested | ● | ● |
context.rootPath | ● | ● |
context.server | ● | ● |
context.user | ● | ● |
webdav.ExternalRequestContext | ● | ● |
webdav.HTTPRequestContext | ● | ● |
httpContext.request | ● | ● |
httpContext.response | ● | ● |
httpContext.setCode | ● | ● |
httpContext.exit | ● | ● |
webdav.Path | ● | ● |
Path.isPath | ● | ● |
path.paths | ● | ● |
path.decode | ● | ● |
path.isRoot | ● | ● |
path.fileName | ● | ● |
path.rootName | ● | ● |
path.parentName | ● | ● |
path.getParent | ● | ● |
path.hasParent | ● | ● |
path.removeRoot | ● | ● |
path.removeFile | ● | ● |
path.getChildPath | ● | ● |
path.clone | ● | ● |
path.toString | ● | ● |
Webdav Class
new webdav.WebDAVServer(options)
options
{Object} Server options.- returns: {WebDAVServer} The server object.
The class WebDAVServer
will make the interface between the HTTP interface and the file systems.
The file systems are the managers of a sub-tree of the server.
server.setFileSystem('/folder1', myFileSystem, callback);
Doing so will tell the server that if a user make a request on the resource /folder1
or one of its children (/folder1/file2
, /folder1/folder2/file3
, etc...), the myFileSystem
will be used. If the client request on the resource /folder2
, it is not mapped to myFileSystem
, then it will call the closest parent file system, which is the root file system (mapped on /
).
The file systems have the role to manage the mapping of its children (which allow a lazy mapping and non-persistent mapping), their content, their properties and their locks.
A file system must inherit from the FileSystem
class which implements a lot of methods to help managing the resources. The sub-class can implement only a part of the methods, letting the FileSystem
class to use its default behaviour.
This mapping system allow to map file systems in other file systems. For instance, you can use a PhysicalFileSystem
to map a real folder on the disk and map in its children a VirtualFileSystem
. This way, /folder1
will be a real folder on the disk but /folder1/virtualFolder
will not be on the disk but in memory only. With this system, you can map whatever file system you want wherever you want.
Each method call to a file system requires a RequestContext
(the context of the request) and a Path
(the path to the resource in the file system : /folder1/folder2/file3
in the file system mapped in /folder1
will have a path equals to /folder2/file3
):
// myFileSystem mapped on /folder1
server.getFileSystem('/folder1/file2.txt', (fs, rootPath, subPath) => {
// Here, subPath === '/file2.txt'
fs.readDir(ctx, subPath, (e, files) => { /* [...] */ });
});
Here, ctx
is the RequestContext
. It will be created with the information from the request, carry the response object for the server and it is a tool kit. If created from outside of a HTTP request, it is possible to create an external RequestContext
instance :
const ctx = server.createExternalContext();
There are some options allowing you to define the user, the headers as if it was from a HTTP request, the url, etc...
Here is the list of supported options :
Key | Default value | Description |
---|---|---|
requireAuthentification | false | Define if your require to be authenticated. |
httpAuthentication | new HTTPBasicAuthentication('default realm') | Define the object which will provide the authentication method (HTTP : Basic, Digest, custom, etc) |
privilegeManager | new PrivilegeManager() | Allow to check the privileges of the user (grant or restrict access). |
rootFileSystem | new VirtualFileSystem() | The root resource to use as / . |
lockTimeout | 3600 | Define the lock timeout (in seconds). |
strictMode | false | Define if the server must blindly follow the WebDAV RFC (true ) or allow more flexibility (false ) (for instance disallow a body in a request which doesn't use a body). |
enableLocationTag | false | Enable the tag <DAV:location> in the response of the PROPFIND requests. It is disabled by default because it is causing trouble in Finder of OS X. |
maxRequestDepth | 1 | Define the maximum value the Depth header can have in a request (negative values = Infinity ). Note that this option can take any number, not only 0 , 1 and Infinity . |
headers | undefined | Define custom headers to provide for every response. This option is of type : { [name: string]: string | string[] } |
Example
const server = new webdav.WebDAVServer({
/* Options */
});
webdav.route(path, server)
path
{String} Route path.server
{WebDAVServer}WebDAVServer
instance.returns
{Function} Thewebapp
router handler.
The method will create a router handler to webapp
. The request which start with path
will be handle by server
instance. Otherwise, server
will call next()
to route the request to the next router for processing.
Example
app.use(webdav.route('/rootpath', server));
WebDAVServer Object
server.rootFileSystem()
- Returns: {FileSystem} The root file system.
Get the root file system which maped '/'.
server.setFileSystem(path, fs[[, override], callback])
path
{String} Path where to mount the file system.fs
{FileSystem} File system to mount.override
{Boolean} Define if the mounting can override a previous mounted file system, default to false.callback
{Function} Argument:success
{Boolean} Containing the status of the mounting.
Map/mount a file system to a path.
Example
You can map a file system to a path in the server. To do so, you can use the method setFileSystem(...) of the WebDAVServer instance.
server.setFileSystem('/myfs', new webdav.PhysicalFileSystem('./test'), (success) => {
console.log(success);
});
This method will fail if a file system is already mapped to this path. To override it, you can use the override argument or remove the file system.
server.setFileSystem('/myfs', new webdav.PhysicalFileSystem('./test'), true, (success) => {
console.log(success);
});
server.removeFileSystem(path[[, checkByReference], callback])
path
{String | FileSystem} Path of the file system or file system to remove.checkByReference
{Boolean} Define if the file systems must be matched by reference or by its serializer's UID, default to true.callback
{Function} Argument:nbRemoved
{Number} Callback containing the number of removed file systems (0 or 1).
Remove a file system. Note that you can remove a file system by its path or by its reference.
Example
server.removeFileSystem('/folder1', callback); // Remove by path
server.removeFileSystem(myFileSystem, callback); // Remove by reference
server.removeFileSystem(myFileSystem, false, callback); // Remove by comparing its serializer unique id (will remove all instances using the serializer of myFileSystem)
server.removeFileSystem(myFileSystem, true, callback); // Remove by reference
server.getFileSystemPath(fs[[, checkByReference], callback])
fs
{FileSystem} File system.checkByReference
{Boolean} Define if the file systems must be matched by reference or by its serializer's UID, default to true.callback
{Function} Argument:path
{webdav.Path | null} The mount path of the file system.
Get the mount path of a file system.
Example
server.getFileSystemPath(myFileSystem, (path) => console.log(path)); // By reference
server.getFileSystemPath(myFileSystem, true, (path) => console.log(path)); // By reference
server.getFileSystemPath(myFileSystem, false, (path) => console.log(path)); // By serializer unique id
server.getFileSystem(path[, callback])
path
{webdav.Path} Requested path.callback
{Function} Callback arguments:fileSystem
{FileSystem} The file system.rootPath
{webdav.Path} The mount path of the file system.subPath
{webdav.Path} The sub path from the mount path to the requested path.
Get synchronously the file system managing the provided path.
Example
server.getFileSystem('/folder1/folder2/file3.txt', (fileSystem, rootPath, subPath) => {
console.log('The path of the file system is :', rootPath);
console.log('The sub path of the requested path is :', subPath); // If rootPath is '/folder1', then subPath is '/folder2/file3.txt'
});
server.getChildFileSystems(parentPath[, callback])
parentPath
{webdav.Path} Path from which list sub file systems.callback
{Function} Callback with {Object[]} result, object containing:fs
{FileSystem} The child file system.path
{webdav.Path} The mount path of the file system.
Get the list of file systems mounted on or under the parentPath.
Example
server.getChildFileSystems(new webdav.Path('/myfs'), childs => {
console.log('Count of child file system:', childs.length); // 0 or more
});
server.on(event, listener)
event
{String} Name of the event..listener
{Function} Listener of the event. with arguments:ctx
{RequestContext} Request context.fs
{FileSystem} File system.path
{webdav.Path} The require path of the file system.data
{Object} Event data.
returns
{WebDAVServer} This.
Events are triggered when a resource is accessed or modified. The server handles the events.
Example
server.on('create', (ctx, fs, path, data) => {
console.log('Resource created; createIntermediates=', data.createIntermediates);
});
server.removeEvent(event[, listener])
event
{String} Name of the event..listener
{Function} Listener of the event.returns
{WebDAVServer} This.
Remove a listener. Clear all the listeners of an event if listener not support.
Example
server.removeEvent('create', myListener);
server.beforeRequest(manager)
manager
{Function} Callback with arguments:ctx
{HTTPRequestContext} Context.next
{Function} Next callback.
Action to execute before an operation is executed when a HTTP request is received.
Example
When executing the before listeners, you can call ctx.exit()
to skip and to send the response and execute the after listeners, skipping the method function. Here is an example :
server.beforeRequest((ctx, next) => {
if(ctx.requested.uri.indexOf('/') !== 0) {
ctx.setCode(400); // Bad request
ctx.exit();
} else {
next();
}
});
If you don't call ctx.exit()
, then you MUST call next()
, otherwise the request execution will stop at the end of the function. Both ctx.exit()
and next()
can be called asynchronously but they must not be called twice. Only on of these functions must be called, not both.
server.afterRequest(manager)
manager
{Function} Callback with arguments:ctx
{HTTPRequestContext} Context.next
{Function} Next callback.
Action to execute after an operation is executed when a HTTP request is received.
Example
server.afterRequest((ctx, next) => {
console.log('>>', ctx.request.method, ctx.requested.uri, '>', ctx.response.statusCode, ctx.response.statusMessage);
next();
});
server.createExternalContext()
returns
{ExternalRequestContext} External request context.
Create a request context as an external request (from outside of the HTTP interface), which allow a script to use the file systems as if it was a request, but without the response object, it will use a custom super-admin user, which the isAdministrator
value equals to true
.
WebDAVServer Events
create
ctx
{RequestContext} Request context.fs
{FileSystem} File system.path
{webdav.Path} The require path of the file system.data
{Object} Event data.
Triggered after resource is created.
data
object includes:
type
{ResourceType} Resource type.createIntermediates
(Boolean) Defines if the operation is allowed to create intermediate resources ('/folder1/folder2/file3', if 'folder2' doesn't exist, it is an intermediate).
ResourceType
has type objects:
webdav.ResourceType.File
webdav.ResourceType.Directory
webdav.ResourceType.Hybrid
webdav.ResourceType.NoResource
before-create
ctx
{RequestContext} Request context.fs
{FileSystem} File system.path
{webdav.Path} The require path of the file system.data
{Object} Event data.
Triggered before a resource is created.
data
object includes:
type
{ResourceType} Resource type.createIntermediates
(Boolean) Defines if the operation is allowed to create intermediate resources ('/folder1/folder2/file3', if 'folder2' doesn't exist, it is an intermediate).
delete
ctx
{RequestContext} Request context.fs
{FileSystem} File system.path
{webdav.Path} The require path of the file system.data
{Object} Event data.
Triggered after a resource is deleted.
data
object includes:
depth
{Integer} Depth of the delete. Might be ignored depending on the implementation. default to -1 means undefined.
before-delete
ctx
{RequestContext} Request context.fs
{FileSystem} File system.path
{webdav.Path} The require path of the file system.data
{Object} Event data.
Triggered before a resource is deleted.
data
object includes:
depth
{Integer} Depth of the delete. Might be ignored depending on the implementation. default to -1 means undefined.
copy
ctx
{RequestContext} Request context.fs
{FileSystem} File system.path
{webdav.Path} The require path of the file system.data
{Object} Event data.
Triggered after a resource is copied.
data
object includes:
pathTo
{webdav.Path} Target path.overwrite
{Boolean} Enable overwrite.overrided
{Boolean} Overwrite copy.depth
{Integer} Depth of the delete. Might be ignored depending on the implementation. default to -1 means undefined.
before-copy
ctx
{RequestContext} Request context.fs
{FileSystem} File system.path
{webdav.Path} The require path of the file system.data
{Object} Event data.
Triggered before a resource is copied.
data
object includes:
pathTo
{webdav.Path} Target path.overwrite
{Boolean} Enable overwrite.depth
{Integer} Depth of the delete. Might be ignored depending on the implementation. default to -1 means undefined.
move
ctx
{RequestContext} Request context.fs
{FileSystem} File system.path
{webdav.Path} The require path of the file system.data
{Object} Event data.
Triggered after a resource is moved.
data
object includes:
pathFrom
{webdav.Path} Source path.pathTo
{webdav.Path} Target path.overwrite
{Boolean} Enable overwrite.overrided
{Boolean} Overwrite move.
before-move
ctx
{RequestContext} Request context.fs
{FileSystem} File system.path
{webdav.Path} The require path of the file system.data
{Object} Event data.
Triggered before a resource is moved.
data
object includes:
pathFrom
{webdav.Path} Source path.pathTo
{webdav.Path} Target path.overwrite
{Boolean} Enable overwrite.
rename
ctx
{RequestContext} Request context.fs
{FileSystem} File system.path
{webdav.Path} The require path of the file system.data
{Object} Event data.
Triggered after a resource is renamed.
data
object includes:
newName
{String} New name.overrided
{Boolean} Same name overwrite.
before-rename
ctx
{RequestContext} Request context.fs
{FileSystem} File system.path
{webdav.Path} The require path of the file system.data
{Object} Event data.
Triggered before a resource is renamed.
data
object includes:
newName
{String} New name.
lock-set
ctx
{RequestContext} Request context.fs
{FileSystem} File system.path
{webdav.Path} The require path of the file system.data
{Object} Event data.
Triggered after a lock is added.
data
object includes:
lock
{Lock} Lock object.
lock
object properties:
uuid
{String} unique identification of lock.userUid
{String} User id.depth
{Integer} Depth of lock for fs-tree. default to -1 mean undefined.expirationDate
{Integer} Lock expiration date times(ms: UNIX timestamp).
before-lock-set
ctx
{RequestContext} Request context.fs
{FileSystem} File system.path
{webdav.Path} The require path of the file system.data
{Object} Event data.
Triggered before a lock is added.
data
object includes:
lock
{Lock} Lock object.
lock-remove
ctx
{RequestContext} Request context.fs
{FileSystem} File system.path
{webdav.Path} The require path of the file system.data
{Object} Event data.
Triggered after a lock is removed.
data
object includes:
uuid
{String} Lock uuid.removed
{Boolean} Lock removed.
before-lock-remove
ctx
{RequestContext} Request context.fs
{FileSystem} File system.path
{webdav.Path} The require path of the file system.data
{Object} Event data.
Triggered before a lock is removed.
data
object includes:
uuid
{String} Lock uuid.
lock-refresh
ctx
{RequestContext} Request context.fs
{FileSystem} File system.path
{webdav.Path} The require path of the file system.data
{Object} Event data.
Triggered after a lock is refreshed.
data
object includes:
uuid
{String} Lock uuid.timeout
{Integer} Lock timeout(ms).lock
{Lock} Lock object.
before-lock-refresh
ctx
{RequestContext} Request context.fs
{FileSystem} File system.path
{webdav.Path} The require path of the file system.data
{Object} Event data.
Triggered before a lock is refreshed.
data
object includes:
uuid
{String} Lock uuid.timeout
{Integer} Lock timeout(ms).
SimpleUser Object
SimpleUser
object is created by the SimpleUserManager
object to record user authentication and file system permission information.
user.username
- {String} User name.
user.password
- {String} User password.
user.isAdministrator
- {Boolean} Is administrator user or not.
TheisAdministrator
property gives full rights to the user, skipping the privilege checking.
user.isDefaultUser
- {Boolean} Is default user or not.
If the webdav server does not need authentication, the default user will be provided when requesting.
user.uid
- {String} Same as uid.
The uid
property is the unique identifier of the user. It must never change. It will be used to uniquely identify a user when locking a resource.
UserManager Class
The user management is not very defined because it is dependent to the authentication method. The Basic
HTTP authentication method can check if a credential is valid by testing the username and the password, but the Digest
HTTP authentication method needs to get the list of all users and test for each if the hashed credential is matching.
Because the users are stored locally, the SimpleUserManager
implementation can be used for both Basic
and Digest
HTTP authentication methods.
new webdav.SimpleUserManager()
returns
{SimpleUserManager}SimpleUserManager
object.
Create simple user manager.
The user manager creates a default user by default. If the webdav server does not need authentication, the default user will be provided when requesting.
Example
const userManager = new webdav.SimpleUserManager();
SimpleUserManager Object
userManager.addUser(name, password[, isAdmin])
name
{String} User name.password
{String} User password.isAdmin
{Boolean} Is administrator or not, default to false. Administrator have all permissions.returns
{SimpleUser} Simple user object.
Add a user by account.
Example
const user = userManager.addUser('user', 'pwd');
userManager.delUser(name)
name
{String} User name.
Delete a user by account.
Example
const user = userManager.delUser('user');
userManager.getUsers(callback)
callback
{Function} Arguments:error
{Error} Error if exist.users
{SimpleUser[]} User array.
Get all user objects included default user.
userManager.getDefaultUser(callback)
callback
{Function} Arguments:user
{SimpleUser} Default user.
Get default user.
userManager.getUserByName(name, callback)
name
{String} User name.callback
{Function} Arguments:error
{Error} Error if exist.user
{SimpleUser} User found.
Get user by name.
userManager.getUserByNamePassword(name, password, callback)
name
{String} User name.callback
{Function} Arguments:error
{Error} Error if exist.user
{SimpleUser} User found.
Get user by name and password.
PrivilegeManager Class
The privileges of a user upon a resource is defined by the instance of the class PrivilegeManager
provided in the server's option privilegeManager
. This object provides a list of methods to tell the server that a resource is accessible by a user or if it is not. SimplePathPrivilegeManager
is an implementation of PrivilegeManager
.
new webdav.SimplePathPrivilegeManager()
returns
{SimplePathPrivilegeManager}SimplePathPrivilegeManager
object.
A SimplePathPrivilegeManager
object check if a user has the required rights based on the given path.
Example
const privilege = new webdav.SimplePathPrivilegeManager();
SimplePathPrivilegeManager Object
privilege.setRights(user, path, rights)
user
{SimpleUser} User object.path
{String} Path string.rights
{String[]} Rights to path.
Set rights to path of user. The rights tree as follow:
all
+--canWrite
| +--canWriteLocks:set or remove lock of resource.
| +--canWriteContent: write content.
| | +--canWriteContentSource: content must be the source or the
| | | computed content.
| | +--canWriteContentTranslated: Contrary to about. Might make
| | no difference depending on the implementation.
| +--canWriteProperties: set or remove property.
+--canRead
+--canReadLocks: Get the lock resource.
+--canReadContent: read content.
| +--canReadContentSource: the content must be the source or the
| | computed content.
| +--canReadContentTranslated: Contrary to about. Might make
| no difference depending on the implementation.
+--canReadProperties: get property of resource.
The following rules apply:
- Parent rights include child rights; em:
canWrite
include [canWriteLocks
,canWriteContent
,canWriteProperties
]; - The child path inherits all rights of the parent path;
all
right contains all rights.
Example
const privilege = new webdav.SimplePathPrivilegeManager();
privilege.setRights(user, '/pyhfs', [ 'all' ]);
privilege.getRights(user, path)
user
{SimpleUser} User object.path
{String} Path string.\returns
{string[]} Rights to path.
Get rights to path of user.
HTTPAuthentication Class
The authentication system is based on the HTTP authentication system. It uses the Authorization
and WWW-Authenticate
headers to provide authentication.
At the moment, only two authentication systems are available in the module :
Basic
Digest
The HTTPAuthentication
has to interface Internal:
askForAuthentication()
getUser(ctx, callback}
The askForAuthentication()
method is used by the server to know what headers the method needs to add to its response.
The getUser()
method is used by the server to get the user of the current request. This method must provide the user authenticated or a default user if possible.
There are two authentication system implemented in the modules : HTTPBasicAuthentication
and HTTPDigestAuthentication
.
new webdav.HTTPBasicAuthentication(userManager[, realm])
userManager
{SimpleUserManager} User manager.realm
{String} A string describing a protected area forWWW-Authenticate
header option, default torealm
. em:WWW-Authenticate: Basic realm="realm
.returns
{HTTPBasicAuthentication}HTTPBasicAuthentication
object.
The class HTTPBasicAuthentication
implements the Basic
authentication system.
Example
const userManager = new webdav.SimpleUserManager();
const auth = new webdav.HTTPBasicAuthentication(userManager);
new webdav.HTTPDigestAuthentication(userManager[, realm])
userManager
{SimpleUserManager} User manager.realm
{String} A string describing a protected area forWWW-Authenticate
header option, default torealm
. em:WWW-Authenticate: Basic realm="realm
.returns
{HTTPDigestAuthentication}HTTPDigestAuthentication
object.
The class HTTPDigestAuthentication
implements the Digest
authentication system and provides a more secure way to authenticate.
Example
const userManager = new webdav.SimpleUserManager();
const auth = new webdav.HTTPDigestAuthentication(userManager);
FileSystem Class
The FileSystem
class has two implementations:
PhysicalFileSystem
: Mapping to the physical file system;VirtualFileSystem
: File system created in cache.
new webdav.PhysicalFileSystem(rootPath)
rootPath
{String} Root path of physical file system.returns
{PhysicalFileSystem}PhysicalFileSystem
object.
Create a physical file system.
Example
const filesystem = new webdav.PhysicalFileSystem('./test');
new webdav.VirtualFileSystem()
returns
{VirtualFileSystem}VirtualFileSystem
object.
Create a virtual file system.
Example
const filesystem = new webdav.VirtualFileSystem();
RequestContext Class
The request context is materialized by the RequestContext
class, it is used to know in which context an operation is asked.
HTTPRequestContext
: ThisHTTPRequestContext
object is created by the server when a request is received.ExternalRequestContext
:server.createExternalContext()
method will create aExternalRequestContext
as an external request (from outside of the HTTP interface), which allow a script to use the file systems as if it was a request, but without the response object, it will use a custom super-admin user, which theisAdministrator
value equals to true.
RequestContext Object
context.requested
- {Object} contain:
uri
{String} The http request url pathname.path
{webdav.Path} Theuri
path object.
The http request uri information.
Example
webdav.route('/root', server); // The server's context root path is `/root`.
// original http request url: /root/subpath
// modified url: /subpath
// context.requested.uri: /subpath
context.rootPath
- {undefined | webdav.Path} The root path object. Undefined if root path is '/'.
The root path is webdav server route path.
Example
webdav.route('/root', server); // The server's context root path is `/root`.
webdav.route('/', server); // context.rootPath undefined.
context.server
- {WebDAVServer}
WebDAVServer
object which create the context.
context.user
- {SimpleUser} User object who access file system.
HTTPRequestContext Object
HTTPRequestContext
inherits all attributes of RequestContext
. In addition, there are some attributes and methods related to HTTP
.
httpContext.request
- {WebRequest}
WebApp
request object.
httpContext.response
- {WebResponse }
WebApp
response object.
httpContext.setCode(code[, message])
code
{Integer} Http response stauts code.message
{String} Http response status message.
Set http response status.
Example
ctx.setCode(404);
httpContext.exit()
End the http response, It will call WebResponse End ()
End the request.
Example
ctx.setCode(404);
ctx.exit();
Path Class
new webdav.Path(path)
path
{ string[] | string | webdav.Path} Path string orwebdav.Path
object.returns
{webdav.Path} The webdav path object.
Create a new webdav path.
Example
new webdav.Path('/myfs/sub');
// or
new webdav.Path(['myfs', 'sub']);
// or
const path1 = new webdav.Path('/myfs/sub');
const path2 = new webdav.Path(path1);
Path.isPath(path)
path
{Object} Path object.returns
{Boolean} The result.
Check if the given object is webdav path or not.
Example
const result = webdav.Path.isPath(path);
Path Object
path.paths
- {String[]} Parts of path.
Example
const path = new webdav.Path('/myfs/sub');
console.log(path.paths); // ['myfs', 'sub']
path.decode()
Use decodeURIComponent
to decode each path string.
path.isRoot()
returns
{Boolean} Is root path or not.
Check the path is root or not.
Example
const path = new webdav.Path('');
// or: const path = new webdav.Path([]);
console.log(path.isRoot()); // true
path.fileName()
returns
{String} Path file name.
Get path file name.
Example
const path = new webdav.Path('/myfs/sub/file.txt');
console.log(path.fileName()); // file.txt
path.rootName()
returns
{String} Path root name(paths[0]
).
Get path root name.
Example
const path = new webdav.Path('/myfs/sub/file.txt');
console.log(path.rootName()); // myfs
path.parentName()
returns
{String} Path parent name(paths[this.paths.length - 2]
).
Get path parent name.
Example
const path = new webdav.Path('/myfs/sub/file.txt');
console.log(path.parentName()); // sub
path.getParent()
returns
{webdav.Path} Parent path.
Get parent path.
Example
const path = new webdav.Path('/myfs/sub/file.txt');
console.log(path.getParent().toString()); // /myfs/sub
path.hasParent()
returns
{Boolean} Has parent or not (this.paths.length >= 2
).
If path has parent or not.
Example
const path = new webdav.Path('/myfs);
console.log(path.hasParent()); // false
path.removeRoot()
returns
{String} Removed root (this.paths.shift()
).
Remove root and return it.
Example
const path = new webdav.Path('/myfs/sub/file.txt');
console.log(path.removeRoot()); // myfs
path.removeFile()
returns
{String} Removed file name (this.paths.pop()
).
Remove file name return it.
Example
const path = new webdav.Path('/myfs/sub/file.txt');
console.log(path.removeFile()); // file.txt
path.getChildPath(childPath)
childPath
{String | Path} Child path sring or sub path object.returns
{Path} Child path object.
Create a child path.
Example
const parent = new webdav.Path('/myfs');
const child = parent.getChildPath('/sub/file.txt');
console.log(child.toString()); // /myfs/sub/file.txt
path.clone()
returns
{Path} Clone path objectt..
Clone path objectt..
path.toString([endsWithSlash])
endsWithSlash
{Boolean} End with slash or not, default to false.returns
{String} Path to string.
Get path string.
Example
const path = new webdav.Path('/myfs/sub');
console.log(path.toString()); // /myfs/sub
console.log(path.toString(true)); // /myfs/sub/
WebDAV Methods
The server support methods to implements the WebDAV specifications, list of available methods:
Method | Description |
---|---|
NotImplemented | Default behavior when the requested method is not implemented. It returns a 501 Not implemented to the client. |
Proppatch | Set/Remove properties to/from a resource. |
Propfind | Get information about a resource (name, properties, locks, etc...). |
Options | Get the list of supported methods. |
Delete | Delete a resource. |
Unlock | Unlock a resource. It needs the Lock-Token header. |
Mkcol | Create a directory type resource. |
Copy | Copy a resource. It needs the Destination header. |
Lock | Lock a resource, preventing it from being written. This method can refresh a lock if the If header is provided. |
Move | Move a resource. It needs the Destination header. |
Head | Make a Get but do not send the content. Allow to test if a resource exists and if it can be read. |
Post | Set the content of a resource or create this one. It is an alias of the Put method. Removing the Put method will keep the Put behavior through the Post method |
Put | Set the content of a resource or create this one. |
Get | Get the content of a resource. |
Example
const WebApp = require('webapp');
const webdav = require('middleware').webdav;
const socket = require('socket');
// Create App
const saddr = socket.sockaddr(socket.INADDR_ANY, 3001);
const app = WebApp.create('webapp', 0, saddr);
// User manager (tells who are the users)
const userManager = new webdav.SimpleUserManager();
const user = userManager.addUser('user', 'pwd', false);
// Privilege manager (tells which users can access which files/folders)
const privilegeManager = new webdav.SimplePathPrivilegeManager();
privilegeManager.setRights(user, '/', [ 'all' ]);
// Create webdav server
const server = new webdav.WebDAVServer({
// HTTP Digest authentication with the realm 'Default realm'
httpAuthentication: new webdav.HTTPDigestAuthentication(userManager, 'Default realm'),
privilegeManager: privilegeManager
});
// Set file system
server.setFileSystem('/', new webdav.PhysicalFileSystem('./root'), (success) => {
console.log(success);
});
// Set after request listener
server.afterRequest((ctx, next) => {
console.log('>>', ctx.request.method, ctx.requested.uri, '>', ctx.response.statusCode, ctx.response.statusMessage);
next();
});
// Mount the WebDAVServer instance
app.use(webdav.route('/', server));
// Start App
app.start();
// Event loop
require('iosched').forever();